
package com.gcloud.mesh.dcs.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gcloud.framework.db.PageResult;
import com.gcloud.mesh.asset.dao.CloudResourceConfigDao;
import com.gcloud.mesh.asset.dao.CloudResourceDao;
import com.gcloud.mesh.asset.dao.DatacenterDao;
import com.gcloud.mesh.asset.dao.IaasDao;
import com.gcloud.mesh.asset.entity.CloudResourceConfigEntity;
import com.gcloud.mesh.asset.entity.CloudResourceEntity;
import com.gcloud.mesh.asset.entity.DatacenterEntity;
import com.gcloud.mesh.asset.entity.IaasEntity;
import com.gcloud.mesh.asset.enums.CloudResourceType;
import com.gcloud.mesh.asset.service.IAssetService;
import com.gcloud.mesh.asset.service.ICloudResourceService;
import com.gcloud.mesh.dcs.chain.FilterChain;
import com.gcloud.mesh.dcs.common.DeviceThresholdTypes;
import com.gcloud.mesh.dcs.dao.*;
import com.gcloud.mesh.dcs.entity.*;
import com.gcloud.mesh.dcs.enums.*;
import com.gcloud.mesh.header.enums.ModelType;
import com.gcloud.mesh.header.enums.MonitorMeter;
import com.gcloud.mesh.header.exception.BaseException;
import com.gcloud.mesh.header.exception.SchedulerErrorCode;
import com.gcloud.mesh.header.msg.dcs.*;
import com.gcloud.mesh.header.vo.asset.CloudResourceItemVo;
import com.gcloud.mesh.header.vo.asset.DatacenterItemVo;
import com.gcloud.mesh.header.vo.asset.NodeItemVo;
import com.gcloud.mesh.header.vo.dcs.*;
import com.gcloud.mesh.monitor.service.StatisticsCheatService;
import com.gcloud.mesh.sdk.RestveleroSDK;
import com.gcloud.mesh.supplier.dao.SupplierDao;
import com.gcloud.mesh.supplier.entity.SupplierEntity;
import com.gcloud.mesh.supplier.enums.SystemType;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.DictCode;
import org.jeecg.common.exception.MyBusinessException;
import org.jeecg.common.exception.ParamException;
import org.jeecg.common.system.vo.DictModel;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.system.entity.SysDict;
import org.jeecg.modules.system.entity.SysDictItem;
import org.jeecg.modules.system.mapper.SysDictItemMapper;
import org.jeecg.modules.system.mapper.SysDictMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URISyntaxException;
import java.security.SecureRandom;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
// @CacheConfig(cacheNames = Module.COMPONENT)
@Slf4j
public class SchedulerService {

	@Autowired
	private SupplierDao supplierDao;

	@Autowired
	private SchedulerJobDao schedulerJobDao;

	@Autowired
	private SchedulerConfigDao schedulerConfigDao;

	@Autowired
	private SchedulerStepDao schedulerStepDao;

	@Autowired
	private AppDao appDao;

	@Autowired
	private ModelScoreDao modelScoreDao;

	@Autowired
	private SysDictMapper sysDictMapper;

	@Autowired
	private SysDictItemMapper sysDictItemMapper;

	@Autowired
	private DatacenterDao datacenterDao;

	@Autowired
	private IAssetService assetService;

	@Autowired
	private IaasDao iaasDao;

	@Autowired
	private SchedulerImagineDao schedulerImagineDao;

	@Autowired
	private CloudResourceDao cloudResourceDao;

	@Autowired
	private CloudResourceConfigDao cloudResourceConfigDao;

	@Autowired
	private ICloudResourceService cloudResourceService;

	@Autowired
	private RestveleroSDK restveleroSDK;

	@Autowired
	private DeviceThresholdTypes deviceType;

	@Autowired
	private StatisticsCheatService statisticsCheatService;

	@Autowired
	private RedisUtil redisUtil;
	
	@Autowired
	private ModelService modelService;

	@Autowired
	private FilterChain filterChain;

	private SecureRandom random = new SecureRandom();

	public int count(String datacenterId) {
		return schedulerJobDao.count(datacenterId);
	}

	public SchedulerJobEntity getJobByStatus(Integer status, String appId) {
		Map<String, Object> props = new HashMap<String, Object>();
		props.put("status", status);
		props.put("app_id", appId);
		return schedulerJobDao.findUniqueByProperties(props);
	}

	public PageResult<SchedulerJobVo> jobPage(PageSchedulerJobMsg msg) {
		List<DatacenterEntity> dcs = datacenterDao.findAll();

		Map<String, String> dcNames = new HashMap<>();
		if (dcs != null) {
			for (DatacenterEntity dc : dcs) {
				dcNames.put(dc.getId(), dc.getName());
			}
		}

		PageResult<SchedulerJobVo> page = schedulerJobDao.page(msg);

		if (page != null && page.getList() != null) {
			for (SchedulerJobVo sjv : page.getList()) {
				sjv.setSrcDatacenterName(dcNames.get(sjv.getSrcDatacenterId()));

				if (StringUtils.isNotBlank(sjv.getDstDatacenterId())) {
					sjv.setDstDatacenterName(dcNames.get(sjv.getDstDatacenterId()));
				}

				if (StringUtils.isNotBlank(sjv.getDstDatacenterId())) {
					sjv.setDstDatacenterName(dcNames.get(sjv.getDstDatacenterId()));
				}

				sjv.setStatusName(SchedulerJobStatus.getByValue(sjv.getStatus()).getName());

				// CloudResourceType type =
				// CloudResourceType.getByType(sjv.getCloudResourceType());
				// if (type != null) {
				// sjv.setCloudResourceTypeName(type.getName());
				// }
				if (sjv.getStatus().equals(SchedulerJobStatus.FAIL.getValue())) {
					List<SchedulerStepEntity> steps = schedulerStepDao.findByProperty("status",
							SchedulerStepStatus.FAIL.getValue());
					if (steps != null) {
						for (SchedulerStepEntity step : steps) {
							sjv.setErrorStep(step.getName());
						}
					}else {
						sjv.setErrorStep("初始化调度任务");
					}
				}
				// 计算百分比
				if (sjv.getStatus().equals(SchedulerJobStatus.SUCCESS.getValue())) {
					sjv.setSchedulerProgress("100");
				} else {
					sjv.setSchedulerProgress(toSchedulerProgress(sjv.getStepCount(), filterChain
							.getChainStepCount(SystemType.getSystemTypeByCnName(sjv.getCloudResourceTypeName()))));
				}
				// if(SystemType.K8S.getCnName().equalsIgnoreCase(sjv.getCloudResourceTypeName())){
				// sjv.setSchedulerProgress(toSchedulerProgress(sjv.getStepCount(),));
				// }
				// if(SystemType.ALI.getCnName().equalsIgnoreCase(sjv.getCloudResourceTypeName())){
				// sjv.setSchedulerProgress(toSchedulerProgress(sjv.getStepCount(),9));
				// }
				// if(SystemType.HUAWEI.getCnName().equalsIgnoreCase(sjv.getCloudResourceTypeName())){
				// sjv.setSchedulerProgress(toSchedulerProgress(sjv.getStepCount(),6));
				// }
			}
		}

		return page;
	}

	/**
	 * 转换为两位小数的字符串
	 * 
	 * @param numerator
	 *            分子
	 * @param denominator
	 *            分母
	 * @return
	 */
	private String toSchedulerProgress(int numerator, int denominator) {
		BigDecimal bd = new BigDecimal(numerator);
		BigDecimal bd2 = new BigDecimal(denominator);
		BigDecimal result = bd.divide(bd2, 2, RoundingMode.HALF_UP);
		result = result.multiply(new BigDecimal(100));
		return result.toString();
	}

	public List<SchedulerStepVo> stepList(@Valid PageSchedulerStepMsg msg) {
		List<SchedulerStepVo> jobs = schedulerStepDao.list(msg.getSchedulerJobId(), SchedulerStepVo.class);
		List<SchedulerStepVo> res = new ArrayList<>();
		if (jobs != null) {
			for (SchedulerStepVo job : jobs) {
				job.setStatusName(SchedulerJobStatus.getByValue(job.getStatus()).getName());
				res.add(job);
			}
		}
		return res;
	}

	public void schedule(SchedulerJobEntity job) throws URISyntaxException {
		Integer tool = job.getSchedulerModelTool();

		DatacenterEntity srcDc = datacenterDao.getById(job.getSrcDatacenterId());
		DatacenterEntity dstDc = datacenterDao.getById(job.getDstDatacenterId());

		if (tool.equals(0)) {
			// TODO mo 新版迁移方法
			JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(job));
			jsonObject.put("srcDatacenterName", srcDc.getName());
			jsonObject.put("dstDatacenterName", dstDc.getName());
			filterChain.start(SystemType.K8S, job.getId(), jsonObject.toString());
			// serverMigrationStrategyContext.exec(SystemType.K8S.getName(),job);
		} else {
			// 虚拟机（华为、阿里）
			// SupplierEntity destSupplier =
			// supplierDao.findOneByProperty("datacenterId",
			// job.getDstDatacenterId());
			// SupplierEntity srcSupplier =
			// supplierDao.findOneByProperty("datacenterId",
			// job.getSrcDatacenterId());

			// 改成获取云平台资源的配置信息
			CloudResourceConfigEntity srcCloudResource = cloudResourceConfigDao.findOneByProperty("cloud_resource_id",
					job.getCloudResourceId());
			CloudResourceConfigEntity destCloudResource = cloudResourceConfigDao.findOneByProperty("cloud_resource_id",
					job.getDstCloudResourceId());

			if (destCloudResource == null || srcCloudResource == null)
				throw new MyBusinessException("找不到目标或源云资源平台");
			if (destCloudResource.getType().equals(SystemType.K8S.getNo()))
				throw new MyBusinessException("目标和源平台资源类型不一致");

			JSONObject jsonObject = JSONObject.parseObject(destCloudResource.getConfig());

			if (destCloudResource.getType().equals(SystemType.HUAWEI.getNo())) {
				// 华为
				jsonObject.put("vmName", job.getInstanceName());// 源
				jsonObject.put("vmId", job.getInstanceId());// 源
				jsonObject.put("destRegionId", jsonObject.getString("regionId"));// 目标
				jsonObject.put("regionId", JSONObject.parseObject(srcCloudResource.getConfig()).getString("regionId"));// 原
				jsonObject.put("accessKey",
						JSONObject.parseObject(srcCloudResource.getConfig()).getString("accessKey"));// 原
				jsonObject.put("secretKey",
						JSONObject.parseObject(srcCloudResource.getConfig()).getString("secretKey"));// 原
			} else {
				// 阿里云
				jsonObject.put("srcAppName", job.getInstanceName());// 源
				jsonObject.put("srcInstanceId", job.getInstanceId());// 源
				jsonObject.put("srcRegionId",
						JSONObject.parseObject(srcCloudResource.getConfig()).getString("regionId"));// 源
				jsonObject.put("accessKey",
						JSONObject.parseObject(srcCloudResource.getConfig()).getString("accessKey"));// 原
				jsonObject.put("secretKey",
						JSONObject.parseObject(srcCloudResource.getConfig()).getString("secretKey"));// 原
			}
			// jsonObject.put("myJobId",job.getId());

			// 新增数据中心名字
			jsonObject.put("srcDatacenterName", srcDc.getName());
			jsonObject.put("dstDatacenterName", dstDc.getName());

			filterChain.start(SystemType.getSystemTypeByNo(destCloudResource.getType()), job.getId(),
					jsonObject.toString());
			// serverMigrationStrategyContext.exec(SystemType.getSystemTypeByNo(destCloudResource.getType()).getName(),jsonObject);
		}

	}


	private String getComparisonOperatorString(Integer comparisonOperator) {
		switch (comparisonOperator) {
		case 0:
			return ">=";
		case 1:
			return ">";
		case 2:
			return "<=";
		case 3:
			return "<";
		case 4:
			return "==";
		case 5:
			return "!=";
		default:
			return "!=";
		}
	}

	public void updateScheduler(UpdateSchedulerVo msg) {
		List<DatacenterEntity> datacenters = datacenterDao.findAll();
		if (datacenters != null) {
			for (DatacenterEntity datacenter : datacenters) {
				if (msg.getDatacenterIds() == null || (!msg.getDatacenterIds().contains(datacenter.getId()))) {
					datacenter.setIsScheduler(false);
				} else {
					datacenter.setIsScheduler(true);

				}
				datacenterDao.update(datacenter);
			}
		}
	}

	public List<SchedulerModelVo> schedulerModelList() {
		List<DictModel> values = sysDictMapper.queryDictItemsByCode(DictCode.SCHEDULER_MODEL.getCode());

		List<SchedulerModelVo> res = new ArrayList<>();
		for (SchedulerModelType value : SchedulerModelType.values()) {
			SchedulerModelVo r = new SchedulerModelVo();
			r.setValue(value.getValue());
			r.setName(value.getName());
			if (values != null && values.size() > 0 && Integer.parseInt(values.get(0).getValue()) == value.getValue()) {
				r.setIsCheck(true);
			} else {
				r.setIsCheck(false);
			}

			res.add(r);
		}
		return res;
	}

	public void updateSchedulerModel(UpdateSchedulerModelMsg type) {

		if (SchedulerModelType.getByType(type.getType()) == null) {
			throw new ParamException(SchedulerErrorCode.TYPE_FORMAT_ERROR);
		}

		SysDict dict = sysDictMapper
				.selectOne(new QueryWrapper<SysDict>().eq("dict_code", DictCode.SCHEDULER_MODEL.getCode()));
		if (dict == null) {
			dict = new SysDict();
			dict.setDictName(DictCode.SCHEDULER_MODEL.getName());
			dict.setDictCode(DictCode.SCHEDULER_MODEL.getCode());
			dict.setDelFlag(CommonConstant.DEL_FLAG_0);
			sysDictMapper.insert(dict);
		}

		SysDictItem sysDictItem = sysDictItemMapper
				.selectOne(new QueryWrapper<SysDictItem>().eq("dict_id", dict.getId()));

		if (sysDictItem != null) {
			sysDictItem.setItemValue(String.valueOf(type.getType()));
			sysDictItemMapper.updateById(sysDictItem);
		} else {
			sysDictItem = new SysDictItem();
			sysDictItem.setDictId(dict.getId());
			sysDictItem.setItemText(SchedulerModelType.getByType(type.getType()).getName());
			sysDictItem.setItemValue(String.valueOf(type.getType()));
			sysDictItemMapper.insert(sysDictItem);
		}
	}

	public PageResult<DatacenterSchedulerConfigVo> datacenterConfigPage(PageDatacenterSchedulerConfigMsg msg) {
		PageResult<DatacenterEntity> page = datacenterDao.pageById(msg.getPageNo(), msg.getPageSize(),
				msg.getDatacenterId(), null, null, DatacenterEntity.class);

		List<DatacenterSchedulerConfigVo> list = new ArrayList<>();
		if (page != null) {
			for (DatacenterEntity datacenter : page.getList()) {
				DatacenterSchedulerConfigVo dsc = new DatacenterSchedulerConfigVo();
				BeanUtils.copyProperties(datacenter, dsc);
				// Map<String,Object> p = new HashMap<>();
				// p.put("datacenterId",datacenter.getId());
				// p.put("type",SystemType.K8S.getName());
				// SupplierEntity supplierEntity =
				// supplierDao.findOneByProperties(p);
				// if(supplierEntity!=null){
				//
				// if(SystemType.K8S.getName().equalsIgnoreCase(supplierEntity.getType())){
				// dsc.setSpType(SystemType.K8S.getName());
				// GceSDK gceSDK = SpringContextUtils.getBean(GceSDK.class);
				// ClusterVo clusterVo =
				// gceSDK.detailCluster(supplierEntity.getClusterId());
				// if(clusterVo!=null && clusterVo.getCluster()!=null){
				// dsc.setCapacity(clusterVo.getCluster().getCapacity());
				// dsc.setRequested(clusterVo.getCluster().getRequested());
				// }
				// }else{
				// dsc.setSpType(SystemType.getSystemTypeByName(supplierEntity.getType()).getName());
				//
				// Object obj = redisUtil.get("job:vmusage:" +
				// datacenter.getId());
				// if(obj!=null){
				// List<DescribeMetricVO> describeMetricVOS =
				// JSONArray.parseArray(obj.toString(),DescribeMetricVO.class);
				// dsc.setDescribeMetricVO(describeMetricVOS);
				// }
				// }
				// }

				List<SchedulerConfigEntity> s = schedulerConfigDao.findByProperty("datacenterId", datacenter.getId());

				if (s != null && !s.isEmpty()) {
					dsc.setSchedulerConfigList(s.stream().map(x -> {
						MyUpdateAppSchedulerConfig c = new MyUpdateAppSchedulerConfig();
						BeanUtils.copyProperties(x, c);
						dsc.setCreateTime(x.getUpdateTime());
						return c;
					}).sorted((x,y)->{
						return SchedulerConfigKey.sortKey(x.getThresholdKey(), y.getThresholdKey());
					}).collect(Collectors.toList()));
				}

				// if (s == null || s.size() == 0) {
				// dsc.setIsSchedulerConfig(false);
				// } else {
				// dsc.setThresholdKey(s.get(0).getThresholdKey());
				// dsc.setThresholdOperation(s.get(0).getThresholdOperation());
				// dsc.setThresholdValue(s.get(0).getThresholdValue());
				// dsc.setIsSchedulerConfig(true);
				// dsc.setCreateTime(s.get(0).getUpdateTime());
				// }

				list.add(dsc);
			}
		}
		PageResult<DatacenterSchedulerConfigVo> result = new PageResult<DatacenterSchedulerConfigVo>();
		result.setList(list);
		result.setPageNo(page.getPageNo());
		result.setPageSize(page.getPageSize());
		result.setTotalCount(page.getTotalCount());
		return result;
	}

	public void updateSchedulerModelTool(UpdateSchedulerModelToolMsg tool) {

		for (Integer i : tool.getTool()) {
			if (SchedulerModelTool.getByType(i) == null) {
				throw new ParamException(SchedulerErrorCode.TOOL_FORMAT_NULL);
			}
		}

		SysDict dict = sysDictMapper
				.selectOne(new QueryWrapper<SysDict>().eq("dict_code", DictCode.SCHEDULER_MODEL_TOOL.getCode()));
		if (dict == null) {
			dict = new SysDict();
			dict.setDictName(DictCode.SCHEDULER_MODEL_TOOL.getName());
			dict.setDictCode(DictCode.SCHEDULER_MODEL_TOOL.getCode());
			dict.setDelFlag(CommonConstant.DEL_FLAG_0);
			sysDictMapper.insert(dict);
		}

		Map<String, Object> columnMap = new HashMap<>();
		columnMap.put("dict_id", dict.getId());
		sysDictItemMapper.deleteByMap(columnMap);

		for (Integer t : tool.getTool()) {
			SysDictItem sysDictItem = new SysDictItem();
			sysDictItem.setDictId(dict.getId());
			sysDictItem.setItemText(SchedulerModelTool.getByType(t).getName());
			sysDictItem.setItemValue(String.valueOf(t));
			sysDictItemMapper.insert(sysDictItem);
		}

	}

	public List<SchedulerModelToolVo> schedulerModelToolList() {
		List<DictModel> values = sysDictMapper.queryDictItemsByCode(DictCode.SCHEDULER_MODEL_TOOL.getCode());

		List<Integer> valueList = new ArrayList<>();
		if (values != null) {
			for (DictModel value : values) {
				valueList.add(Integer.parseInt(value.getValue()));
			}
		}

		List<SchedulerModelToolVo> res = new ArrayList<>();
		for (SchedulerModelTool value : SchedulerModelTool.values()) {
			SchedulerModelToolVo r = new SchedulerModelToolVo();
			r.setType(value.getType());
			r.setValue(value.getValue());
			r.setName(value.getName());
			if (values != null && values.size() > 0 && valueList.contains(value.getValue())) {
				r.setIsCheck(true);
			} else {
				r.setIsCheck(false);
			}

			res.add(r);
		}
		return res;
	}

	public void updateSchedulerStrategyConfig(UpdateSchedulerStrategyConfigMsg config) {

		if (SchedulerStrategyConfig.getByType(config.getConfig()) == null) {
			throw new ParamException(SchedulerErrorCode.CONFIG_FORMAT_ERROR);
		}

		SysDict dict = sysDictMapper
				.selectOne(new QueryWrapper<SysDict>().eq("dict_code", DictCode.SCHEDULER_STRATEGY_CONFIG.getCode()));
		if (dict == null) {
			dict = new SysDict();
			dict.setDictName(DictCode.SCHEDULER_STRATEGY_CONFIG.getName());
			dict.setDictCode(DictCode.SCHEDULER_STRATEGY_CONFIG.getCode());
			dict.setDelFlag(CommonConstant.DEL_FLAG_0);
			sysDictMapper.insert(dict);
		}

		Map<String, Object> deleteMap = new HashMap<>();
		deleteMap.put("dict_id", dict.getId());
		sysDictItemMapper.deleteByMap(deleteMap);

		SysDictItem sysDictItem = new SysDictItem();
		sysDictItem.setDictId(dict.getId());
		sysDictItem.setItemText(SchedulerModelTool.getByType(config.getConfig()).getName());
		sysDictItem.setItemValue(String.valueOf(config.getConfig()));
		sysDictItemMapper.insert(sysDictItem);

	}

	public List<SchedulerStrategyConfigVo> schedulerStrategyConfigList() {
		List<DictModel> values = sysDictMapper.queryDictItemsByCode(DictCode.SCHEDULER_STRATEGY_CONFIG.getCode());

		List<SchedulerStrategyConfigVo> res = new ArrayList<>();
		for (SchedulerStrategyConfig value : SchedulerStrategyConfig.values()) {
			SchedulerStrategyConfigVo r = new SchedulerStrategyConfigVo();
			r.setValue(value.getValue());
			r.setName(value.getName());
			if (values != null && values.size() > 0 && Integer.parseInt(values.get(0).getValue()) == value.getValue()) {
				r.setIsCheck(true);
			} else {
				r.setIsCheck(false);
			}

			res.add(r);
		}
		return res;
	}

	public void updateSchedulerStrategyRule(UpdateSchedulerStrategyRuleMsg rule) {

		JSONObject json = JSONObject.parseObject(rule.getRule());
		String beginTime = json.getString("beginTime");
		String endTime = json.getString("endTime");

		if (!isBefore(beginTime, endTime)) {
			throw new ParamException("开始时间必须在结束时间之前!");
		}
		SysDict dict = sysDictMapper
				.selectOne(new QueryWrapper<SysDict>().eq("dict_code", DictCode.SCHEDULER_STRATEGY_RULE.getCode()));
		if (dict == null) {
			dict = new SysDict();
			dict.setDictName(DictCode.SCHEDULER_STRATEGY_RULE.getName());
			dict.setDictCode(DictCode.SCHEDULER_STRATEGY_RULE.getCode());
			dict.setDelFlag(CommonConstant.DEL_FLAG_0);
			sysDictMapper.insert(dict);
		}

		Map<String, Object> columnMap = new HashMap<>();
		columnMap.put("dict_id", dict.getId());
		sysDictItemMapper.deleteByMap(columnMap);

		SysDictItem sysDictItem = new SysDictItem();
		sysDictItem.setDictId(dict.getId());
		sysDictItem.setItemText("迁移策略执行规则");
		sysDictItem.setItemValue(rule.getRule());
		sysDictItemMapper.insert(sysDictItem);

	}

	private boolean isBefore(String beginTimeStr, String endTimeStr) {
		SimpleDateFormat df = new SimpleDateFormat("HH:mm");
		try {
			Date begin = df.parse(beginTimeStr);
			Date end = df.parse(endTimeStr);
			Calendar beginTime = Calendar.getInstance();
			beginTime.setTime(begin);
			Calendar endTime = Calendar.getInstance();
			endTime.setTime(end);
			if (beginTime.before(endTime)) {
				return true;
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return false;
	}

	public SchedulerStrategyRuleVo getSchedulerStrategyRule() {
		List<DictModel> values = sysDictMapper.queryDictItemsByCode(DictCode.SCHEDULER_STRATEGY_RULE.getCode());
		if (values != null && values.size() > 0) {
			SchedulerStrategyRuleVo res = new SchedulerStrategyRuleVo();
			res.setRule(values.get(0).getValue());
			return res;
		} else {
			return null;
		}
	}

	public SchedulerEffectPredictionVo schedulerEffectPrediction(SchedulerEffectPredictionMsg msg) {

		SchedulerEffectPredictionVo res = new SchedulerEffectPredictionVo();

		AppVo appVo = appDao.getVoById(msg.getAppId());
		CloudResourceItemVo vm = cloudResourceService.detail(appVo.getCloudResourceId());
		// NodeItemVo node = assetService.detailNode(vm.getNodeId(), "");
		DatacenterItemVo datacenter = assetService.detailDatacenter(vm.getDatacenterId(), "");
		SysDict sysDict = sysDictMapper.selectOne(
				new LambdaQueryWrapper<SysDict>().eq(SysDict::getDictCode, DictCode.SCHEDULER_MODEL.getCode()));
		ModelType modelType = ModelType.get(msg.getModelType());

		List<ModelScoreEntity> sourceScores = modelScoreDao.getPageOrderByTime(modelType, datacenter.getId(),
				ModelScoreEntity.class);
		List<ModelScoreEntity> destScores = modelScoreDao.getPageOrderByTime(modelType, msg.getDatacenterId(),
				ModelScoreEntity.class);

		int diff = 0;
		if (sourceScores.size() > 0 && destScores.size() > 0) {
			diff = sourceScores.get(0).getTotalScore() - destScores.get(0).getTotalScore();
		}

		// 预测系数
		Double difference = (double) (100 + diff) / 100;
		BigDecimal differenceb = new BigDecimal(difference);
		difference = differenceb.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
		
		GetModelFactorsMsg fm = new GetModelFactorsMsg();
		fm.setModelType(msg.getModelType());
		List<ModelFactorVo> factors = modelService.getModelFactors(fm);
		
		List<SchedulerEffectPredictionFactorVo> vos = new ArrayList<SchedulerEffectPredictionFactorVo>();
		for(ModelFactorVo factor : factors){
			if(factor.getEnabled()){
				SchedulerEffectPredictionFactorVo vo = new SchedulerEffectPredictionFactorVo();
				
				String valueStr = statisticsCheatService.latestSample(factor.getFactorType(), appVo.getDatacenterId());
				Double value = Double.parseDouble(valueStr);
				BigDecimal valueb = new BigDecimal(value);
				value = valueb.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
				
				if (difference > 0) {
					Double imagine = value * difference;
					BigDecimal imagineb = new BigDecimal(imagine);
					imagine = imagineb.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
					
					vo.setImagine(imagine);
				}else {
					vo.setImagine(-1d);
				}
				
				vo.setFactorType(factor.getFactorType());
				vo.setFactorName(factor.getFactorName());
				vo.setBefore(value);
				vo.setDifference(difference);
				vo.setUnit(factor.getUnit());
				vos.add(vo);
			}
		}
		
		res.setId(msg.getAppId());
		res.setFactors(vos);
		
		return res;
	}

	public SchedulerResultAnalysisVo schedulerResultAnalysis(SchedulerResultAnalysisMsg msg) {

		SchedulerResultAnalysisVo res = new SchedulerResultAnalysisVo();

		ModelType modelType = ModelType.get(SchedulerModelDict.get(msg.getSchedulerModel().toString()).name());

		SchedulerImagineEntity entity = schedulerImagineDao.get(modelType, msg.getAppId(), msg.getSrcDatacenterId(),
				msg.getDstDatacenterId(), SchedulerImagineEntity.class);

		
		String[] imagines = entity.getImagines().split(",");
		String[] values = entity.getValues().split(",");
		String[] factorTypes = entity.getFactorTypes().split(",");
		
		if(imagines.length != values.length){
			throw new ParamException("指标因子不正确!");
		}
		
		List<SchedulerEffectPredictionFactorVo> vos = new ArrayList<SchedulerEffectPredictionFactorVo>();
		
		for(int i = 0; i < imagines.length; i++) {
			SchedulerEffectPredictionFactorVo vo = new SchedulerEffectPredictionFactorVo();
			vo.setFactorType(factorTypes[i]);
			vo.setImagine(Double.parseDouble(imagines[i]));
			vo.setAfter(Double.parseDouble(values[i]));
			vo.setFactorName(MonitorMeter.getNameByMeter(factorTypes[i]));
			vo.setUnit(MonitorMeter.getByMeter(factorTypes[i]).getUnit());
			vos.add(vo);
		}
		
		res.setFactors(vos);
		res.setId(msg.getAppId());
		
		return res;
	}

	private double random() {
		// Random random = new Random();
		int value = random.nextInt(40) + 70;
		double res = (double) (value * 0.01);
		BigDecimal b = new BigDecimal(res);
		double d = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

		return d;
	}

	public void migrateResource(MigrateResourceVo msg) {
		doMigrate(msg);
	}

	public void updateSchedulerJob(SchedulerJobEntity job) {

		AppVo app = appDao.getVoById(job.getAppId());
		if (app == null)
			return;
		CloudResourceEntity cloudResource = cloudResourceDao.getById(app.getCloudResourceId());

		List<DictModel> tools = sysDictMapper.queryDictItemsByCode(DictCode.SCHEDULER_MODEL_TOOL.getCode());

		if (tools != null) {
			for (DictModel value : tools) {
				if (value.getValue().equals("0")) { // k8s
					if (cloudResource.getType() == 1) {
						job.setSchedulerModelTool(Integer.parseInt(value.getValue()));
					}
				} else { // vm
					if (cloudResource.getType() == 0) {
						SupplierEntity supplierEntity = supplierDao.findOneByProperty("datacenterId",
								cloudResource.getDatacenterId());
						// TODO mo
						// 华为
						// 阿里
						if (supplierEntity == null) {
							job.setSchedulerModelTool(Integer.parseInt(value.getValue()));
						} else {
							int t = SystemType.ALI.getName().equalsIgnoreCase(supplierEntity.getType()) ? 1 : 2;
							job.setSchedulerModelTool(t);
						}
					}
				}
			}
		}

		List<DictModel> configs = sysDictMapper.queryDictItemsByCode(DictCode.SCHEDULER_STRATEGY_CONFIG.getCode());
		if (configs != null) {
			for (DictModel value : configs) {
				job.setSchedulerStrategyConfig(Integer.parseInt(value.getValue()));
			}
		}

		// List<DictModel> models =
		// sysDictMapper.queryDictItemsByCode(DictCode.SCHEDULER_MODEL.getCode());
		// if (models != null) {
		// for (DictModel value : models) {
		// job.setSchedulerModel(Integer.parseInt(value.getValue()));
		// }
		// }

		schedulerJobDao.update(job);
	}

	private void doMigrate(MigrateResourceVo vo) {
		IaasEntity srcIaas = iaasDao.getById(vo.getSrcNodeId());
		if (srcIaas == null) {
			throw new BaseException(SchedulerErrorCode.NODE_NOT_EXIST);
		}
		IaasEntity dstIaas = iaasDao.getById(vo.getDstNodeId());
		if (dstIaas == null) {
			throw new BaseException(SchedulerErrorCode.NODE_NOT_EXIST);
		}
		List<CloudResourceEntity> cloudResources = cloudResourceDao.findByProperty("datacenterId",
				srcIaas.getDatacenterId());
		if (cloudResources != null) {
			for (CloudResourceEntity cloudResource : cloudResources) {
				log.debug("开始需要迁移的云资源{}", cloudResource.getName());
				List<AppEntity> apps = appDao.findByProperty("cloud_resource_id", cloudResource.getId());
				for (AppEntity app : apps) {
					// TODO 调度到目标集群
					if (StringUtils.isNotBlank(dstIaas.getDatacenterId())
							&& StringUtils.isNotBlank(vo.getDstNodeId())) {
						SchedulerJobEntity readyEntity = getJobByStatus(SchedulerJobStatus.READY.getValue(),
								app.getId());
						SchedulerJobEntity progressEntity = getJobByStatus(SchedulerJobStatus.PROGRESS.getValue(),
								app.getId());
						SchedulerJobEntity schedulerJob = new SchedulerJobEntity();
						if (readyEntity == null && progressEntity == null) {
							schedulerJob.setAppId(app.getId());
							schedulerJob.setId(UUID.randomUUID().toString());
							schedulerJob.setStatus(SchedulerJobStatus.READY.getValue());
							schedulerJob.setSrcDatacenterId(srcIaas.getDatacenterId());
							schedulerJob.setAppName(app.getName());
							// CloudResourceEntity cloudResource =
							// cloudResourceMap.get(app.getCloudResourceId());
							if (cloudResource != null) {
								schedulerJob.setCloudResourceName(cloudResource.getName());
								schedulerJob.setCloudResourceTypeName(
										CloudResourceType.getByType(cloudResource.getType()).getName());
								schedulerJob.setCloudResourceId(cloudResource.getId());
							}
							schedulerJob.setDstDatacenterId(dstIaas.getDatacenterId());
							schedulerJob.setDstNodeId(vo.getDstNodeId());
							schedulerJob.setSourceNodeId(vo.getSrcNodeId());
							schedulerJobDao.save(schedulerJob);
						} else {
							log.info("[CheckSchedulerThreshold] Have PROGRESS or READY state schedulerJob!");
						}
					}
				}
			}
		}

	}

	public Double checkDataCenterNeedMigrate(String datacenterId, String type) {
		Map<String, Object> map = new HashMap<>();
		map.put("datacenter_id", datacenterId);
		map.put("threshold_key", type);
		SchedulerConfigEntity entity = schedulerConfigDao.findOneByProperties(map);
		if (entity != null) {
			return entity.getThresholdValue();
		}
		return null;
	}

	public int updateJobInstanceId(String jobId, String destInstanceId) {
		// StringBuffer buffer = new StringBuffer();
		// buffer.append(" update set instance_id = ? where id = ? ");
		// this.
		int result = schedulerJobDao.updateJobInstanceId(jobId, destInstanceId);
		return result;
	}
}
